<template>
  <Mapbox :mapOnLoadCB="mapOnLoadCB"></Mapbox>
  <button id='pause'></button>
</template>

<script>
import {ref} from "vue"
import Mapbox from "@/components/common/Mapbox.component.vue"
import MapboxCommonService from "@/service/map/MapboxCommonService"

export default {
  name: "AddAnimateLine.component",
  components: {Mapbox},
  setup() {

    let mapStore = ref({});
    let mapOnLoadCB = (map) => {
      mapStore.value = map;
      MapboxCommonService.setCZBP(map, [0, 0], 0.5)

      // Create a GeoJSON source with an empty lineString.
      let geojson = {
        "type": "FeatureCollection",
        "features": [{
          "type": "Feature",
          "geometry": {
            "type": "LineString",
            "coordinates": [
              [0, 0]
            ]
          }
        }]
      };

      let speedFactor = 30; // number of frames per longitude degree
      let animation; // to store and cancel the animation
      let startTime = 0;
      let progress = 0; // progress = timestamp - startTime
      let resetTime = false; // indicator of whether time reset is needed for the animation
      let pauseButton = document.getElementById('pause');

      // add the line which will be modified in the animation
      map.addLayer({
        'id': 'line-animation',
        'type': 'line',
        'source': {
          'type': 'geojson',
          'data': geojson
        },
        'layout': {
          'line-cap': 'round',
          'line-join': 'round'
        },
        'paint': {
          'line-color': '#ed6498',
          'line-width': 5,
          'line-opacity': .8
        }
      });

      startTime = performance.now();

      // click the button to pause or play
      pauseButton.addEventListener('click', () => {
        pauseButton.classList.toggle('pause');
        if (pauseButton.classList.contains('pause')) {
          cancelAnimationFrame(animation);
        } else {
          resetTime = true;
          animateLine();
        }
      });

      // reset startTime and progress once the tab loses or gains focus
      // requestAnimationFrame also pauses on hidden tabs by default
      document.addEventListener('visibilitychange', () => {
        resetTime = true;
      });

      // animated in a circle as a sine wave along the map.
      const animateLine = (timestamp) => {
        if (resetTime) {
          // resume previous progress
          startTime = performance.now() - progress;
          resetTime = false;
        } else {
          progress = timestamp - startTime;
        }

        // restart if it finishes a loop
        if (progress > speedFactor * 360) {
          startTime = timestamp;
          geojson.features[0].geometry.coordinates = [];
        } else {
          let x = progress / speedFactor;
          // draw a sine wave with some math.
          let y = Math.sin(x * Math.PI / 90) * 40;
          // append new coordinates to the lineString
          geojson.features[0].geometry.coordinates.push([x, y]);
          // then update the map
          map.getSource('line-animation').setData(geojson);
        }
        // Request the next frame of the animation.
        animation = requestAnimationFrame(animateLine);
      }

      animateLine();
    };

    return {
      mapOnLoadCB
    }
  }
}
</script>

<style scoped lang="scss">
#pause {
  position: absolute;
  left: 10px;
  top: 10px
}

#pause::after {
  content: 'Pause';
}

#pause.pause::after {
  content: 'Play';
}
</style>